using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Ares.ProxyFile;
using System.IO;
using System.Net;
using System.Threading;
using Ares.Walker;
using System.Resources;

namespace Ares
{
    public partial class AresForm : Form
    {
        private int LastSortColumn;
        private bool Reverse = false;
        private WalkerBase Walker = null;
        private ResourceManager RM = null;

        private delegate void SetStatusBarTextHandler(string AText, int Panel);
        private delegate void LogEventHandler(string AText);

        public AresForm()
        {
            InitializeComponent();
            TPTorOptions.Enabled = true;
        }        
        

        public void LogGet(string AText)
        {
            AText = DateTime.Now.ToLongTimeString() +": "+ AText;
            LBGetLog.Items.Insert(0, AText);
        }

        public void LogPost(string AText)
        {
            LBPostLog.Items.Insert(0, AText);
        }

        public void SetStatusBarText(string AText, int Panel)
        {
            this.SB.Panels[Panel].Text = AText;
            Application.DoEvents();
        }

        public void WaitHandler(int Minutes, int Seconds)
        {
            if (this.InvokeRequired)
            {
                SetStatusBarTextHandler d = new SetStatusBarTextHandler(this.SetStatusBarText);
                this.Invoke(d, new object[] { Minutes.ToString() + ":" + Seconds.ToString() ,0});
            }            
        }


        private void AresForm_Load(object sender, EventArgs e)
        {
            RM = new ResourceManager("Ares.ResStrings", typeof(AresForm).Assembly);            

            string fname=Path.GetDirectoryName(Application.ExecutablePath)+"\\proxylist.txt";            
            ProxyList list = new ProxyList(fname);            

            foreach (ProxyServer server in list)
            {
                ListViewItem item = new ListViewItem();
                item.Text = server.IP;
                item.SubItems.Add(server.Port.ToString());
                item.SubItems.Add(server.Anonymity);
                item.SubItems.Add(server.Country);
                item.Checked = true;
                LVServers.Items.Add(item);
            }
            LVServers.ListViewItemSorter = new ServerItemsComparer(0, Reverse);
        }

        private void MISelectAll_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in LVServers.Items)
            {
                item.Checked = true;
            }
        }

        private void MIDeselectAll_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in LVServers.Items)
            {
                item.Checked = false;
            }
        }

        private void MISelectAnonymous_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in LVServers.Items)
            {                
                if (item.SubItems[2].Text.ToLower() == "anonymous")
                {
                    item.Checked = true;
                }
                else
                {
                    item.Checked = false;
                }
            }
        }

        private void MISelectHighAnonymous_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in LVServers.Items)
            {
                if (item.SubItems[2].Text.ToLower() == "high-anonymous")
                {
                    item.Checked = true;
                }
                else
                {
                    item.Checked = false;
                }
            }
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in LVServers.Items)
            {
                item.Checked = !item.Checked;
            }
        }

        private void LVServers_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            if (e.Column == LastSortColumn)
                Reverse = !Reverse;
            else
            {
                LVServers.Columns[LastSortColumn].ImageIndex = -1;
                Reverse = false;
                LastSortColumn = e.Column;                
            }
            LVServers.ListViewItemSorter = new ServerItemsComparer(e.Column,Reverse);
            if (Reverse)
                LVServers.Columns[LastSortColumn].ImageIndex = 0;
            else
                LVServers.Columns[LastSortColumn].ImageIndex = 1;
        }

        private void BtnGetStart_Click(object sender, EventArgs e)
        {
            BtnGetStart.Enabled = false;
            BtnGetStop.Enabled = true;
            TPPost.Enabled = false;
            TPSettings.Enabled = false;
            LBGetLog.Items.Clear();
            LogGet(RM.GetString("WalkerStart"));

            TorManager tm = null;

            string[] arr;
            if (RBUseProxy.Checked)
            {
                arr = new string[LVServers.CheckedItems.Count];
                for (int i = 0; i < LVServers.CheckedItems.Count; i++)
                {
                    arr[i] = "http://" + LVServers.CheckedItems[i].Text + ":" + LVServers.CheckedItems[i].SubItems[1].Text;
                }
            }
            else
            {
                arr = new string[1];
                arr[0] = "http://127.0.0.1:8118/";

                string configFile = new FileInfo(Application.ExecutablePath).Directory.ToString()+"\\torrc";                
                tm = new TorManager(TBTorPath.Text,configFile);
                tm.ShowTorWindow = CBShowTor.Checked;
                tm.Start();
            }

            GetWalker WalkerGet = new GetWalker(TBGetURL.Text, arr, Convert.ToInt32(UDWalkCount.Text), Convert.ToInt32(UDMinutes.Text), Convert.ToInt32(UDSeconds.Text), Convert.ToInt32(UDTimeOut.Text));
            this.Walker = WalkerGet;            
            WalkerGet.Wait += new WalkerWaitEventHandler(this.WaitHandler);
            WalkerGet.Error += new WalkerErrorEventHandler(WalkerGet_Error);
            WalkerGet.Sent += new WalkerSentEventHandler(WalkerGet_Sent);
            WalkerGet.Sending += new WalkerSendingEventHandler(WalkerGet_Sending);
            WalkerGet.Start();
            while (!WalkerGet.Finished)
            {
                Thread.Sleep(100);
                Application.DoEvents();
            }

            WalkerGet = null;

            if (RBUseTor.Checked)
            {
                tm.Stop();               
            }

            TPPost.Enabled = true;
            TPSettings.Enabled = true;
            BtnGetStart.Enabled = true;
            BtnGetStop.Enabled = false;
            SetStatusBarText("", 0);
            LogGet(RM.GetString("WalkerFinished"));
        }

        void WalkerGet_Sending(int No, string Proxy)
        {
            if (this.InvokeRequired)
            {
                Delegate d = new LogEventHandler(this.LogGet);
                string s = String.Format(RM.GetString("WalkerSending"), No, Proxy);
                this.Invoke(d, new object[] { s });
            }   
        }

        void WalkerGet_Sent(int No, string Proxy)
        {
            if (this.InvokeRequired)
            {
                Delegate d = new LogEventHandler(this.LogGet);
                this.Invoke(d, new object[] { RM.GetString("WalkerSent") });
            }
        }

        void WalkerGet_Error(Exception E)
        {
            if (this.InvokeRequired)
            {
                Delegate d = new LogEventHandler(this.LogGet);
                this.Invoke(d, new object[] { String.Format(RM.GetString("WalkerError"), E.Message) });
            }
        }        

        private void BtnGetStop_Click(object sender, EventArgs e)
        {
            Walker.Terminate();            
            BtnGetStop.Enabled = false;            
        }

        private void BtnAddValue_Click(object sender, EventArgs e)
        {
            try
            {
                string str = AddValue.GetValue();
                LBValues.Items.Add(str);
            }
            catch(Exception)
            {

            }
        }

        private void BtnValueDel_Click(object sender, EventArgs e)
        {
            LBValues.Items.RemoveAt(LBValues.SelectedIndex);
        }

        private void AresForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (Walker != null)
            {
                Walker.Terminate();                
            }
        }

        private void BtnPostStart_Click(object sender, EventArgs e)
        {
            BtnPostStart.Enabled = false;
            BtnPostStop.Enabled = true;
            TPGet.Enabled = false;
            TPSettings.Enabled = false;
            LBPostLog.Items.Clear();
            LogPost(RM.GetString("WalkerStart"));

            TorManager tm = null;

            string[] arr;
            if (RBUseProxy.Checked)
            {
                arr = new string[LVServers.CheckedItems.Count];
                for (int i = 0; i < LVServers.CheckedItems.Count; i++)
                {
                    arr[i] = "http://" + LVServers.CheckedItems[i].Text + ":" + LVServers.CheckedItems[i].SubItems[1].Text;
                }
            }
            else
            {
                arr = new string[1];
                arr[0] = "http://127.0.0.1:8118/";
                string configFile = new FileInfo(Application.ExecutablePath).Directory.ToString() + "\\torrc";                
                tm = new TorManager(TBTorPath.Text, configFile);
                tm.ShowTorWindow = CBShowTor.Checked;
                tm.Start();
            }
            
            string s = "";
            foreach (string field in LBValues.Items)
            {
                s += "&" + field;
            }
            s = s.Remove(0, 1);
            
            PostWalker WalkerPost = new PostWalker(TBPostUrl.Text, arr, Convert.ToInt32(UDWalkCount.Text), Convert.ToInt32(UDMinutes.Text), Convert.ToInt32(UDSeconds.Text), Convert.ToInt32(UDTimeOut.Text),s);
            this.Walker = WalkerPost;
            WalkerPost.Wait += new WalkerWaitEventHandler(WaitHandler);
            WalkerPost.Error += new WalkerErrorEventHandler(WalkerPost_Error);
            WalkerPost.Sent += new WalkerSentEventHandler(WalkerPost_Sent);
            WalkerPost.Sending += new WalkerSendingEventHandler(WalkerPost_Sending);
            WalkerPost.Start();
            while (!WalkerPost.Finished)
            {
                Thread.Sleep(100);
                Application.DoEvents();
            }

            WalkerPost = null;

            if (RBUseProxy.Checked)
            {
                tm.Stop();
            }

            TPPost.Enabled = true;
            TPSettings.Enabled = true;
            BtnPostStart.Enabled = true;
            BtnPostStop.Enabled = false;
            SetStatusBarText("", 0);
            LogPost(RM.GetString("WalkerFinished"));
        }

        void WalkerPost_Sending(int No, string Proxy)
        {
            if (this.InvokeRequired)
            {
                Delegate d = new LogEventHandler(this.LogPost);
                string s = String.Format(RM.GetString("WalkerSending"), No, Proxy);
                this.Invoke(d, new object[] { s });
            }   
        }

        void WalkerPost_Sent(int No, string Proxy)
        {
            if (this.InvokeRequired)
            {
                Delegate d = new LogEventHandler(this.LogPost);
                this.Invoke(d, new object[] { RM.GetString("WalkerSent") });
            }
        }

        void WalkerPost_Error(Exception E)
        {
            if (this.InvokeRequired)
            {
                Delegate d = new LogEventHandler(this.LogPost);
                this.Invoke(d, new object[] { String.Format(RM.GetString("WalkerError"), E.Message) });
            }
        }

        private void BtnPostStop_Click(object sender, EventArgs e)
        {
            Walker.Terminate();
            BtnPostStop.Enabled = false;
        }

        private void BtnUp_Click(object sender, EventArgs e)
        {
            int index = LBValues.SelectedIndex;
            if (index == -1)
                return;
            if (index == 0)
                return;

            object str = LBValues.Items[index];
            LBValues.Items.RemoveAt(index);
            LBValues.Items.Insert(index - 1, str);
            LBValues.SelectedIndex = index - 1;
        }

        private void BtnDown_Click(object sender, EventArgs e)
        {
            int index = LBValues.SelectedIndex;
            if (index == -1)
                return;
            if (index == (LBValues.Items.Count-1))
                return;

            object str = LBValues.Items[index];
            LBValues.Items.RemoveAt(index);
            LBValues.Items.Insert(index + 1, str);
            LBValues.SelectedIndex = index + 1;
        }

        private void LBValues_DoubleClick(object sender, EventArgs e)
        {
            if (LBValues.SelectedIndex == -1)
                return;
            string str = (string)LBValues.SelectedItem;
            try
            {
                str = AddValue.EditValue(str);
                LBValues.Items[LBValues.SelectedIndex] = str;
            }
            catch (Exception)
            {
                return;
            }
        }

        private void RBUseTor_CheckedChanged(object sender, EventArgs e)
        {
            TPTorOptions.Enabled = RBUseTor.Checked;
            LVServers.Enabled = !RBUseTor.Checked;
        }

        private void BtnBrowseTor_Click(object sender, EventArgs e)
        {            
            if (OFDTor.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                MessageBox.Show(OFDTor.FileName);
            }
        }      
    }  
}